#include "FileSystemScanner.h"

#include <list>
#include "boost/filesystem.hpp"
#include "boost/format.hpp"

#include "FileMatch.h"
#include "Util.h"

using namespace analyzer;

FileSystemScanner::FileSystemScanner(boost::shared_ptr<AbstractFileFilter> fileFilter) : AbstractFileSystemScanner(fileFilter)
{
	// empty constructor
}


FileSystemScanner::~FileSystemScanner(void)
{
	// empty destructor
}

std::vector<FileInfo> FileSystemScanner::filterFiles(std::string directory, bool includeSubDirectories) {

	using namespace boost::filesystem;

	std::vector<FileInfo> files;
	directory_iterator end;
	std::list<path> filesToVisit;
	path p(directory);
	path tmpPath;
	FileMatch match;
	
	log(DEBUG, "FileSystemScanner", "filterFiles", "Method entered.");
	
	// puts the root path into the list
	filesToVisit.push_back(p);
	
	// TODO additional checking if directoryPath points to acctual directory woudl be usefeull and that directory really exists
	
	// continues if there are still directories to visit
	while(filesToVisit.size() > 0) {
		// gets the first element from the list
		tmpPath = filesToVisit.front();
		filesToVisit.pop_front();
		
		log(DEBUG, "FileSystemScanner", "filterFiles", boost::format("Scanning directory: %1%") % (tmpPath.filename()));
		
		// iterates overa all files in the directory
		try {
			for (directory_iterator it(tmpPath); it != end; ++it)
			{
				// checks if the entry is a file
				if(is_regular_file(*it)) {
					
					// if the file is mached by the filter then it is added to the result
					if((match = getFileFilter()->acceptFile(it->path().filename().string()))) {
						log(DEBUG, "FileSystemScanner", "filterFiles", boost::format("File: %1% matched") % (it -> path().filename().string()));
						
						files.push_back(FileInfo(it->path().filename().string(), it->path().string(), match.getFileType()));
					}
				} else if(is_directory(*it)) {
					// else if the files is a directory then add it to the list of files to visit
					if(includeSubDirectories) {
						filesToVisit.push_back(*it);
					}
				}
			}
		}
		catch (boost::filesystem3::filesystem_error& e) {
			if (e.code() == boost::system::errc::permission_denied) {
				log(ERROR, boost::format("Permission denied when accessing: %1%") % tmpPath.string());
			}else {
				throw e;
			}
		}
	}
	
	log(DEBUG, "FileSystemScanner", "filterFiles", "Method exited.");
	
	// returns the result
	return files;
}
/*
[Wed Jun  1 16:40:09 2011] [INFO] Scaning files in directory: test_files/test-multiple/
boost::filesystem::directory_iterator::construct: Permission denied: "test_files/test-multiple/ehhh"
timon@saya /root/fu/ZPR/project-zpr $ ./build/CycleFinder test_files/test-multiple/ -r 
[Wed Jun  1 16:40:34 2011] [INFO] Scaning files in directory: test_files/test-multiple/
boost::filesystem::status: Permission denied: "test_files/test-multiple/ehhh/f.h"
*/
